﻿using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Text;

using Ordinaire.Social.Data;

namespace Ordinaire.Commerce.Data
{
    /// <summary>
    /// Use this to capture all purchases.
    /// </summary>
    [Table]
    public class Invoices : Data<int, string>
    {
        #region Variables

        /// <summary>
        /// Storage for constraint "FK_Invoices_People"
        /// </summary>
        protected EntityRef<People> people;

        /// <summary>
        /// Storage for constraint "FK_Invoices_Organisations"
        /// </summary>
        protected EntityRef<Organisations> organisations;

        /// <summary>
        /// Storage for related records in table "InvoiceItems".
        /// </summary>
        protected EntitySet<InvoiceItems<Invoices>> invoiceItems = new EntitySet<InvoiceItems<Invoices>>();

        #endregion

        #region Property methods

        /// <summary>
        /// Get or set the entry unique identifier.
        /// </summary>
        [Column(IsPrimaryKey = true, IsDbGenerated = true, UpdateCheck = UpdateCheck.Never)]
        public override int Id
        {
            get { return base.Id; }
            set { base.Id = value; }
        }

        /// <summary>
        /// Gets or sets the invoice serial number.
        /// </summary>
        [Column(DbType = "nvarchar(50) NULL", UpdateCheck = UpdateCheck.Never)]
        public virtual string SerialNo { get; set; }

        /// <summary>
        /// Gets or sets the purchase date.
        /// </summary>
        [Column(DbType = "datetime NULL", UpdateCheck = UpdateCheck.Never)]
        public virtual DateTime Date { get; set; }

        /// <summary>
        /// Gets or sets whom (as individual) this purchase belong to.
        /// </summary>
        [Column(DbType = "int NULL", CanBeNull = true, UpdateCheck = UpdateCheck.Never)]
        public virtual int? PersonId { get; set; }

        /// <summary>
        /// Gets or sets whom (as organisation) this purchase belong to.
        /// </summary>
        [Column(DbType = "int NULL", CanBeNull = true, UpdateCheck = UpdateCheck.Never)]
        public virtual int? OrganisationId { get; set; }

        /// <summary>
        /// Gets or sets the discount amount given for this purchase.
        /// </summary>
        [Column(DbType = "decimal(18,5) NOT NULL DEFAULT(0)", UpdateCheck = UpdateCheck.Never)]
        public virtual decimal Discount { get; set; }

        /// <summary>
        /// Gets or sets the tax amount charged for this purchase.
        /// </summary>
        [Column(DbType = "decimal(18,5) NOT NULL DEFAULT(0)", UpdateCheck = UpdateCheck.Never)]
        public virtual decimal Tax { get; set; }

        #region Overrides IAudit

        /// <summary>
        /// Get or set the username who created this entry.
        /// </summary>
        [Column(DbType = "nvarchar(10) NOT NULL", UpdateCheck = UpdateCheck.Never)]
        public override string CreatedBy
        {
            get { return base.CreatedBy; }
            set { base.CreatedBy = value; }
        }

        /// <summary>
        /// Get or set the date when the entry was first created.
        /// </summary>
        [Column(DbType = "datetime NOT NULL", UpdateCheck = UpdateCheck.Never)]
        public override DateTime? CreateDate
        {
            get { return base.CreateDate; }
            set { base.CreateDate = value; }
        }

        /// <summary>
        /// Get or set the username who last updated this entry.
        /// </summary>
        [Column(DbType = "nvarchar(10) NULL", UpdateCheck = UpdateCheck.Never)]
        public override string UpdatedBy
        {
            get { return base.UpdatedBy; }
            set { base.UpdatedBy = value; }
        }

        /// <summary>
        /// Get or set the date when the entry was last updated.
        /// </summary>
        [Column(DbType = "datetime NULL", UpdateCheck = UpdateCheck.Never)]
        public override DateTime? UpdateDate
        {
            get { return base.UpdateDate; }
            set { base.UpdateDate = value; }
        }

        #endregion

        #region Association

        /// <summary>
        /// Gets or sets the associated data to table 'People'.
        /// </summary>
        [Association(Name = "FK_Invoices_People", IsForeignKey = true, ThisKey = "PersonId", OtherKey = "Id", Storage = "people")]
        public virtual People People
        {
            get { return this.people.Entity; }
            set { this.people.Entity = value; }
        }

        /// <summary>
        /// Gets or sets the associated data to table 'Organisations'.
        /// </summary>
        [Association(Name = "FK_Invoices_Organisations", IsForeignKey = true, ThisKey = "OrganisationId", OtherKey = "Id", Storage = "organisations")]
        public virtual Organisations Organisations
        {
            get { return this.organisations.Entity; }
            set { this.organisations.Entity = value; }
        }

        /// <summary>
        /// Gets or sets the associated data to table 'PurchaseGoods'.
        /// </summary>
        [Association(ThisKey = "Id", OtherKey = "ForeignId", Storage = "invoiceItems")]
        public EntitySet<InvoiceItems<Invoices>> InvoiceItems
        {
            get { return this.invoiceItems; }
        }

        #endregion

        #endregion
    }

    /// <summary>
    /// Contains list of extension methods for Ordinaire.Commerce.Data.Invoices.
    /// </summary>
    public static class InvoiceExtension
    {
        /// <summary>
        /// Converts invoice data into an instance of Ordinaire.Commerce.Invoice.
        /// </summary>
        /// <param name="data">the invoice data</param>
        /// <returns>Ordinaire.Commerce.Invoice instance representing the invoice data</returns>
        public static Invoice ToInvoice(this Invoices data)
        {
            Invoice invoice = data.ToInvoice<Invoice>();
            invoice.Details = data.InvoiceItems.ToList().ToInvoiceDetails();
            return invoice;
        }

        /// <summary>
        /// Converts invoice data into an instance of specified type derived from Ordinaire.Commerce.Invoice.
        /// </summary>
        /// <typeparam name="TInvoice">type derived from Ordinaire.Commerce.Invoice</typeparam>
        /// <param name="data">the invoice data</param>
        /// <returns>instance of specified type representing the invoice data</returns>
        public static TInvoice ToInvoice<TInvoice>(this Invoices data)
            where TInvoice : Invoice
        {
            if (data == null)
            {
                return null;
            }

            Entity<int> party = null;
            if (data.OrganisationId > 0)
            {
                party = data.Organisations.ToOrganisation();
            }
            else if (data.PersonId > 0)
            {
                party = data.People.ToPerson();
            }

            TInvoice invoice = typeof(TInvoice).Instance<TInvoice>();
            invoice.Id       = data.Id;
            invoice.Date     = data.Date;
            invoice.SerialNo = data.SerialNo;
            invoice.Party    = party;
            invoice.Discount = data.Discount;
            invoice.Tax      = data.Tax;

            return invoice;
        }
    }
}
